<?php

namespace App\Service;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;


class BangCache
{
    // laravel 自带的缓存测试
    // TODO  laravel 只有redis、memcached，但不包括 database才支持 tags

    // TODO
    //  通过缓存key制作缓存标签，生成缓存绑定操作成功
    //  但：制作绑定缓存的时候 makeBang 字段必须在模型中设置
    //   删除的时候，必须是模型中设置的缓存字段

    // 根据thinkphp制作绑定缓存
    public function getCache($key)
    {
        if (empty($key)) {
            return null;
        }

        return Cache::get($key);
    }

    // 所有参数制作 key
    public function makeCacheKey($table, $key, ...$params)
    {
        if (count($params) === 0) {
            return md5($table . '_' . $key);
        }

        // 根据参数制作key
        //  如果生成的参数中有对象转换的字符串，则返回 false
        $string = $table . '_' . $key . '_' . var_export($params, 1);

        // 判断key里面是否有对象的字符串  \Closure::__set_state(array(____))   方案2
        //   \Closure::__set_state(array(____)) 里面 array(____) 的下划线可能是四个，也可能是2个，所以使用 __set_state 作为判断
        // PHP 8.0+：使用 str_contains()（区分大小写）
        if (str_contains($string, '__set_state')) {
            return '';
        }

        // TODO
        //  md5为32位或者64位
        //  hash是256位的，比md5产生重复的可能性更低
        //  在一个程序中，如果使用 md5($data) 生成缓存 key，则存在一定的重复率，但是概率很低，所以仍然使用 md5
        //  在 PHP 中，可使用 hash('sha256', $data) 替代 md5($data)

        return md5($string);
    }

    // 制作表绑定
    public function makeBang($table, $map = [], $self = '')
    {
        $ds   = '_';
        $bang = [];
        if (empty($map)) {
            $bang[] = $table . ($self ? $ds . $self : '');

            return $bang;
        }

        // TODO $field  字段必须在模型中设置
        foreach ($map as $field => $val) {
            $name = $table . $ds . $field . $ds;
            if (is_array($val)) {
                foreach ($val as $_val) {
                    $bang[] = $name . $_val;
                }
            } else {
                $bang[] = $name . $val;
            }
        }

        return $bang;
    }

    // 删除某个tag
    public function deleteTag($tag)
    {
        $tags = is_array($tag) ? $tag : [$tag];
        foreach ($tags as $tag) {
            $keys = Cache::get($tag);
            if ($keys) {
                foreach ($keys as $key) {
                    Cache::forget($key);
                }
            }
        }
    }

    // 添加到 tag
    public function addTag($tag, $key)
    {
        $keys = Cache::get($tag);
        if ($keys) {
            if (!in_array($key, $keys)) {
                $keys[] = $key;
            }
        } else {
            $keys = [$key];
        }

        Cache::put($tag, $keys);
    }

    // 添加缓存
    public function addCache($key, $value)
    {
        if ($key) {
            Cache::add($key, $value);
        }
    }


}

